package visitor;

/**
 * 详细解释这句话 《在结构不变的情况下动态改变对于内部元素的动作》
 * 例子场景 电脑城装机
 * 首先主机的主要三大件是不可能变的 【cpu】【memory】【board】。 对应 《在结构不变的情况》
 * 通过 ChannelVisitor 改变 ComputerPart 内部初始价格 所有调用 ComputerPart 的visitor被ChannelVisitor所改变
 *
 * 核心是City的部件是固定的 变的是 对部件价格方法代理上的内容。
 * 相当于把if else 判断不同硬件的方式抽离出来了。
 *
 * 构建流程原理
 * 就是把现有价格交个代理商处理
 *
 * 【编译器】
 *  compiler AST 从右向左
 *  5+7*(4-3)+9 从右向左
 *                       +
 *                    +      9
 *                  5   ...
 *                  分析 + 左边右边是不是类型对 做类型检查
 *                  根据这个AST树生成中间代码 在5前在5后加上什么代码
 *                  做编译器需要不停访问AST树
 *
 *                  需要对每个操作数 操作符做检查。
 *                  如果传统if else 对每个节点都检查 如果要更换所有节点检查相当于所有if else重写
 *                  如果用了visitor直接换检查。
 *  这个模式多数用在编译器上。
 */

/**
 * 渠道商拿货 拿什么产品？
 * 【cpu】【memory】【board】
 * 在原有的价格上做折扣
 */
abstract class ChannelVisitor{
    abstract void cpu(ComputerPart c);
    abstract void memory(ComputerPart c);
    abstract void board(ComputerPart c);
}

/**
 * 种类硬件的规范 【cpu】【memory】【board】
 * 1.对外销售首先要有价
 * 2.接待不同的渠道商
 */
abstract class ComputerPart{
    abstract double getPrice();
    abstract void visitor(ChannelVisitor c);
}

/**
 * 装机城
 */
abstract class ComputerCity{
    abstract void getCpuPic(ChannelVisitor c);
    abstract void getMemoryPic(ChannelVisitor c);
    abstract void getBoardPic(ChannelVisitor c);
}


class Cpu extends ComputerPart{

    @Override
    double getPrice() {
        return 1.1;
    }

    @Override
    void visitor(ChannelVisitor c) {
        c.cpu(this);
    }
}

class Memory extends ComputerPart{

    @Override
    double getPrice() {
        return 2.2;
    }

    @Override
    void visitor(ChannelVisitor c) {
        c.memory(this);
    }
}

class Board extends ComputerPart{

    @Override
    double getPrice() {
        return 3.3;
    }

    @Override
    void visitor(ChannelVisitor c) {
        c.board(this);
    }
}

class City extends ComputerCity{
    ComputerPart cpu = new Cpu();
    ComputerPart memory = new Memory();
    ComputerPart board = new Board();

    @Override
    void getCpuPic(ChannelVisitor c) {
        cpu.visitor(c);
    }

    @Override
    void getMemoryPic(ChannelVisitor c) {
        memory.visitor(c);
    }

    @Override
    void getBoardPic(ChannelVisitor c) {
        board.visitor(c);
    }
}

/**
 * 渠道1
 */
class C extends ChannelVisitor{
    private double basePic = 3;
    @Override
    void cpu(ComputerPart c) {
        System.out.println(c.getPrice()*basePic);
    }

    @Override
    void memory(ComputerPart c) {
        System.out.println(c.getPrice()*basePic);
    }

    @Override
    void board(ComputerPart c) {
        System.out.println(c.getPrice()*basePic);
    }
}

public class Visitor {
    public static void main(String[] args) {
        System.out.println("visitor");

        City city = new City();
        C c = new C();

        city.getBoardPic(c);
        city.getCpuPic(c);
        city.getMemoryPic(c);
    }
}
